#include"Sock.hpp"
#include<sys/select.h>
#include<sys/time.h>
#include<unistd.h>
#include<sys/types.h>

#define NUM (sizeof(fd_set)*8) //select最多可以监视的fd个数
#define INVALID_FD -1 //无效的fd
int fd_array[NUM]; //记录需要被监视读事件的fd

void Usage(std::string proc)
{
  cout << "Usage\n\t" << proc <<" port " << endl;
  exit(1);
}



int main(int argc,char* argv[])
{
  if(argc != 2)
  {
    Usage(argv[0]);
  }
  uint16_t port = atoi(argv[1]);
  int listen_sock = Sock::Socket();
  Sock::Bind(listen_sock,port);
  Sock::Listen(listen_sock);
  
  fd_array[0] = listen_sock;//需要监视 监听套接字上的读事件是否就绪
  //先将fd_array所有位置初始化为无效
  for(int i = 1;i<NUM;i++)
  {
    fd_array[i] = INVALID_FD;
  }
  cout <<"已将fd_array：1~ " << NUM-1 <<"位置初始化为无效" << endl;
  for(;;)
  {
    //每一次都需要重新设置读/写/异常文件描述符集
    fd_set readfds; 
    FD_ZERO(&readfds);//初始化读文件描述符集
    int max_fd = fd_array[0];//,fd_array[0]放的是监听套接字,需要记录最大的有效fd值, +1作为select的第一个参数
    for(int i = 1;i<NUM;i++)
    {
      if(fd_array[i] == INVALID_FD)
      { 
        continue;
      }
      FD_SET(fd_array[i],&readfds); //设置readfds
      max_fd = max(max_fd,fd_array[i]);
    }

    cout <<"当前max_fd:" << max_fd << endl;
    struct timeval t{5,0};//5s超时
    int n = select(max_fd+1,&readfds,nullptr,nullptr,&t);
    switch(n)
    {
      case 0:
        cout <<"timeout 超时！！！" << endl; 
        break;
      case -1:
        cerr <<"select err !!!" << endl;
        break;
      default:
        //有事件就绪,就绪的事件保存在输入输出型参数当中
        cout <<"有事件就绪！！！" << endl;
        for(int i = 0;i<NUM;i++)
        {
           if(fd_array[i] ==INVALID_FD)
           {
             continue;
           }
           
           if(FD_ISSET(fd_array[i],&readfds))
           {
            cout <<"有读取事件就绪" << endl;
            if(fd_array[i] == listen_sock) //监听套接字上的读取事件就绪
            {
              int new_sock = Sock::Accept(listen_sock);
              cout <<"监听套接字上有读取事件就绪！！ new_sock:" << new_sock   << endl;
              int pos = 1;
              for(;pos < NUM;pos++)
              {
                if(fd_array[pos] == INVALID_FD)
                {
                  break;
                }
              }
              if(pos <NUM)
              {
                cout <<new_sock <<"被放到了fd_array数组中"<<pos<<"位置" << endl;
                fd_array[pos]  = new_sock;
              }
              else 
              {
                cout <<"服务器已经满载！！close该连接！" << endl; 
                close(new_sock);
              }
            }
            else  //与客户端建立连接的socket上读取事件就绪
            {
              cout <<"sock:" << fd_array[i]<<"上有读取事件就绪！" << endl;
              char buf[1024] = {0};
              ssize_t res = read(fd_array[i],buf,sizeof(buf) - 1) ;
              if(res > 0)
              {
                buf[res] = '\0';
                cout <<"sock:" <<fd_array[i] <<" client#" << buf << endl;
              }
              else if(res == 0)
              {
                cout <<"sock:" << fd_array[i] << " client quit -->close & fd_array[i] = INVALID_FD" << endl;
                close(fd_array[i]);
                fd_array[i] = INVALID_FD;
              }
              else 
              {
                cout <<"sock:" << fd_array[i] << " read falied  -->close & fd_array[i] = INVALID_FD" << endl;
                close(fd_array[i]);
                fd_array[i] = INVALID_FD;
              }
            }
           }
        }
        break;
    }
  }
  close(listen_sock);
  return 0;
}
